use std::collections::HashMap;
use std::fs::File;
use std::io::{self, BufRead};
use std::path::Path;

pub fn converter(input: &str) -> String {
    let converter = PinyinConverter::new("word.txt", "weipinyin.txt").unwrap();

    let mut result = String::new();
    let mut index = 0;
    for c in input.chars() {
        if c.is_ascii() {
            continue;
        }
        else {
            let unicode = c as u32;
            match converter.convert_to_weipinyin(unicode) {
                Some(weipinyin) => {
                    if index == 0 {
                        let first_char = weipinyin.chars().next().unwrap().to_ascii_uppercase();
                        let remaining_chars = weipinyin.chars().skip(1).collect::<String>();
                        let res = format!("{}{}", first_char, remaining_chars);
                        result.push_str(&res);
                    }
                    else {
                        result.push_str(&weipinyin)  
                    }
                    if index != input.chars().count() -1 {
                        result.push(' ');
                    }
                },
                None => result.push(c),
            }
        }
        index += 1;
    }
    result

}

#[derive(Debug)]
struct PinyinConverter {
    unicode_to_pinyin: HashMap<u32, String>,
    pinyin_to_weipinyin: HashMap<String, String>,
}

impl PinyinConverter {
    fn new(unicode_pinyin_file: &str, weipinyin_file: &str) -> io::Result<Self> {
        let unicode_to_pinyin = Self::load_unicode_to_pinyin(unicode_pinyin_file)?;
        let pinyin_to_weipinyin = Self::load_pinyin_to_weipinyin(weipinyin_file)?;
        Ok(PinyinConverter {
            unicode_to_pinyin,
            pinyin_to_weipinyin,
        })
    }

    fn load_unicode_to_pinyin(file: &str) -> io::Result<HashMap<u32, String>> {
        let mut map = HashMap::new();
        let file = File::open(file)?;
        let reader = io::BufReader::new(file);

        for line in reader.lines() {
            let line = line?;
            let parts: Vec<&str> = line.split_whitespace().collect();
            if parts.len() > 1 {
                let unicode = u32::from_str_radix(parts[0], 16).unwrap();
                let mut pinyin_origin: String = parts[1].to_string().to_lowercase();
                pinyin_origin.pop().unwrap().to_string();
                map.insert(unicode, pinyin_origin);
            }
        }
        Ok(map)
    }

    fn load_pinyin_to_weipinyin(file: &str) -> io::Result<HashMap<String, String>> {
        let mut map = HashMap::new();
        let file = File::open(file)?;
        let reader = io::BufReader::new(file);

        for line in reader.lines() {
            let line = line?;
            let parts: Vec<&str> = line.split_whitespace().collect();
            if parts.len() == 2 {
                let pinyin = parts[0].to_string();
                let weipinyin = parts[1].to_string();
                map.insert(pinyin, weipinyin);
            }
        }
        Ok(map)
    }

    fn convert_to_weipinyin(&self, unicode: u32) -> Option<String> {
        if let Some(pinyins) = self.unicode_to_pinyin.get(&unicode) {
            //println!("pinyins: {:?}, unicode: {}", pinyins, unicode);
            let mut result = Vec::new();
            if let Some(weipinyin) = self.pinyin_to_weipinyin.get(pinyins) {
                result.push(weipinyin.clone());
            }
            Some(result.join(" "))
        } else {
            None
        }
    }
}